package com.company.cloud.pay.modules.third.service;

import cn.hutool.core.util.StrUtil;
import com.company.cloud.pay.core.enums.SignType;
import com.company.cloud.pay.core.kit.WxPayKit;
import com.company.cloud.pay.modules.api.constant.PayTradeType;
import com.company.cloud.pay.modules.api.request.PayOrderCloseRequest;
import com.company.cloud.pay.modules.api.request.PayOrderQueryRequest;
import com.company.cloud.pay.modules.api.request.PayOrderRequest;
import com.company.cloud.pay.modules.cache.model.PayApiConfig;
import com.company.cloud.pay.modules.third.factory.CloudPayApiService;
import com.company.cloud.pay.modules.third.models.ThirdPayResp;
import com.company.cloud.pay.modules.third.models.ThirdQueryOrderResp;
import com.company.cloud.pay.modules.third.models.ThirdUnifiedOrderResp;
import com.company.cloud.pay.modules.third.utils.WxPayApiConfigKit;
import com.company.cloud.pay.modules.third.utils.WxPayApiParamKit;
import com.company.cloud.pay.modules.third.utils.WxPayStateConvertKit;
import com.company.cloud.pay.modules.wxpay.WxPayApi;
import com.company.cloud.pay.modules.wxpay.WxPayApiConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

public class WxCloudPayApiService implements CloudPayApiService {

    private final static Logger logger = LoggerFactory.getLogger(WxCloudPayApiService.class);

    /**
     * 统一下单
     */
    @Override
    public ThirdUnifiedOrderResp unifiedOrder(PayApiConfig payConfig, PayOrderRequest request) {
        ThirdUnifiedOrderResp returnData = new ThirdUnifiedOrderResp();

        WxPayApiConfig wxApiConfig = WxPayApiConfigKit.getWxPayApiConfig(payConfig);
        Map<String, String> params = WxPayApiParamKit.getUnifiedOrderParam(wxApiConfig, request);
        returnData.addReq(params);
        String xmlResult = WxPayApi.pushOrder(params);
        returnData.addResp(xmlResult);

        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            returnData.addRetError(returnMsg);
            return returnData;
        }

        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            returnData.addRetError(returnMsg);
            return returnData;
        }


        if (PayTradeType.WX_NATIVE.getCode().equals(request.getPtt().getCode())) {
            String prepayId = resultMap.get("prepay_id");
            String codeUrl = resultMap.get("code_url");
            Map<String, String> packageParams = new HashMap<String, String>();
            packageParams.put("prepayId", prepayId);
            packageParams.put("codeUrl", codeUrl);
            returnData.setBiz(packageParams);
        } else if (PayTradeType.WX_APP.getCode().equals(request.getPtt().getCode())) {
            String prepayId = resultMap.get("prepay_id");
            Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxApiConfig.getAppId(), wxApiConfig.getMchId(), prepayId,
                    wxApiConfig.getApiKey(), SignType.MD5);
            returnData.setBiz(packageParams);
        } else {
            String prepayId = resultMap.get("prepay_id");
            Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxApiConfig.getAppId(),
                    wxApiConfig.getApiKey(), SignType.MD5);
            returnData.setBiz(packageParams);
        }

        return returnData;
    }

    /**
     * 订单查询
     */
    @Override
    public ThirdQueryOrderResp queryOrder(PayApiConfig payConfig, PayOrderQueryRequest request) {
        ThirdQueryOrderResp returnData = new ThirdQueryOrderResp();
        WxPayApiConfig wxApiConfig = WxPayApiConfigKit.getWxPayApiConfig(payConfig);
        Map<String, String> params = WxPayApiParamKit.getOrderQueryParam(wxApiConfig, request);
        returnData.addReq(params);
        String xmlResult = WxPayApi.orderQuery(params);
        returnData.addResp(xmlResult);
        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            returnData.addRetError(returnMsg);
            return returnData;
        }
        boolean verifyFlag = WxPayKit.verifyNotify(params, wxApiConfig.getApiKey());
        if (!verifyFlag) {
            returnData.addRetError("返回参数，验签失败");
            return returnData;
        }
        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            String errCode = resultMap.get("err_code");
            String errCodeDes = resultMap.get("err_code_des");
            returnData.addRetError(StrUtil.format("{}:{}", errCode, errCodeDes));
            return returnData;
        }

        returnData.setOpenId(resultMap.get("openid"));
        returnData.setIsSubscribe(resultMap.get("is_subscribe"));
        returnData.setTradeType(resultMap.get("trade_type"));
        returnData.setTradeState(resultMap.get("trade_state"));
        returnData.setBankType(resultMap.get("bank_type"));
        returnData.setTotalFee(resultMap.get("total_fee"));
        returnData.setTransactionId(resultMap.get("transaction_id"));
        returnData.setOutTradeNo(resultMap.get("out_trade_no"));
        returnData.setAttach(resultMap.get("attach"));
        returnData.setTimeEnd(resultMap.get("time_end"));
        returnData.setState(WxPayStateConvertKit.convertPayState(returnData.getTradeState()));
        return returnData;
    }

    /**
     * 关闭订单
     */
    @Override
    public ThirdPayResp closeOrder(PayApiConfig payConfig, PayOrderCloseRequest request) {
        ThirdPayResp returnData = new ThirdPayResp();
        WxPayApiConfig wxApiConfig = WxPayApiConfigKit.getWxPayApiConfig(payConfig);
        Map<String, String> params = WxPayApiParamKit.getCloseOrderParam(wxApiConfig, request);
        returnData.addReq(params);
        String xmlResult = WxPayApi.closeOrder(params);
        returnData.addResp(xmlResult);
        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            returnData.addRetError(returnMsg);
            return returnData;
        }
        boolean verifyFlag = WxPayKit.verifyNotify(params, wxApiConfig.getApiKey());
        if (!verifyFlag) {
            returnData.addRetError("返回参数，验签失败");
            return returnData;
        }
        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            String errCode = resultMap.get("err_code");
            String errCodeDes = resultMap.get("err_code_des");
            returnData.addRetError(StrUtil.format("{}:{}", errCode, errCodeDes));
            return returnData;
        }
        return returnData;
    }


}
